package datasource

import (
  "fmt"
  "go-caipu/pkg/plugins/log"
  "net/url"
  "regexp"
  "strings"
)

var logger = log.New("datasource")

// requiredURL contains the set of data sources that require a URL.
var requiredURL = map[string]bool{}

type URLValidationError struct {
  Err error
  URL string
}

// Error returns the error message.
func (e URLValidationError) Error() string {
  return fmt.Sprintf("validation of data source URL %q failed: %s", e.URL, e.Err.Error())
}

// nolint:unused
// Unwrap returns the wrapped error.
// Used by errors package.
func (e URLValidationError) Unwrap() error {
  return e.Err
}

// reURL is a regexp to detect if a URL specifies the protocol. We match also strings where the actual protocol is
// missing (i.e., "://"), in order to catch these as invalid when parsing.
var reURL = regexp.MustCompile("^[^:]*://")

func ValidateURL(typeName, urlStr string) (*url.URL, error) {
  // Check for empty URLs
  if _, exists := requiredURL[typeName]; exists && strings.TrimSpace(urlStr) == "" {
    return nil, URLValidationError{Err: fmt.Errorf("empty URL string"), URL: ""}
  }

  var u *url.URL
  var err error
  switch strings.ToLower(typeName) {
  case "oss":
  default:
    logger.Debug("Applying default URL parsing for this data source type", "type", typeName, "url", urlStr)

    // Make sure the URL starts with a protocol specifier, so parsing is unambiguous
    if !reURL.MatchString(urlStr) {
      logger.Debug(
        "Data source URL doesn't specify protocol, so prepending it with http:// in order to make it unambiguous",
        "type", typeName, "url", urlStr)
      urlStr = fmt.Sprintf("http://%s", urlStr)
    }
    u, err = url.Parse(urlStr)
  }
  if err != nil {
    return nil, URLValidationError{Err: err, URL: urlStr}
  }

  return u, nil

}
